using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
namespace AnguaRPGEngine.Library.Sockets
{ 
    #region BaseSocket Region
    /// <summary>
    /// contains functionality common to both the client and host socket
    /// </summary>
    public abstract class BaseSocket : IDisposable
    {
        /// <summary>
        /// raised when a socket error occurs
        /// </summary>
        public event SocketErrorEventHandler OnSocketError;
        /// <summary>
        /// raised when a general error occurs
        /// </summary>
        public event GeneralErrorEventHandler OnGeneralError;
        /// <summary>
        /// raised when data is sent
        /// </summary>
        public event SendEventHandler OnSend;
        /// <summary>
        /// raised when socket disconnects
        /// </summary>
        public event ClientClosingDelegate OnDisconnect;

        //2008/9/25 - BV - this isn't used for anything
        ///// <summary>
        ///// value indicating whether socket is currently connected
        ///// </summary>
        //protected bool currentlyConnected = false;
        /// <summary>
        /// size of the receive buffer
        /// </summary>
        protected int receiveBufferSize = 10240;

        #region Constructor Region
        /// <summary>
        /// base constructor to create object
        /// </summary>
        public BaseSocket()
        {
        }
        #endregion

        #region Common Socket Event Region
        /// <summary>
        /// raises the OnDisconnect event
        /// </summary>
        protected void RaiseOnDisconnect()
        {            
            if (OnDisconnect != null)
            {
                OnDisconnect();
            }
        }

        /// <summary>
        /// raises the socket's OnSocketError event
        /// </summary>
        /// <param name="e">the SocketException object</param>
        protected void RaiseOnSocketError(SocketException e)
        {
            if (OnSocketError != null)
            {
                OnSocketError(this, e);
            }
        }

        /// <summary>
        /// raises the general error event
        /// </summary>
        /// <param name="e">the Exception object</param>
        protected void RaiseOnGeneralError(Exception e)
        {
            if (OnGeneralError != null)
            {
                OnGeneralError(this, e);
            }
        }

        /// <summary>
        /// raises the socket's OnSend event
        /// </summary>
        /// <param name="bytesSent">number of bytes sent</param>
        protected void RaiseOnSend(int bytesSent)
        {
            if (OnSend != null)
            {
                OnSend(bytesSent);
            }
        }
        #endregion

        #region IDisposable Members
        /// <summary>
        /// disposes the base object
        /// </summary>
        public virtual void Dispose()
        {
            //
            // Release all event Handlers DSJ 4/27/07
            //
            OnDisconnect = null;
            OnSend = null;
            OnSocketError = null;
            OnGeneralError = null;
        }

        #endregion

        /// <summary>
        /// Get's the ipaddress of a host... if it's dotted ipaddress it doesn't go out to dns.
        /// </summary>
        /// <param name="host">i.e. 192.168.0.7</param>
        /// <returns>the IPAddress object</returns>
        public static IPAddress GetIPAddress(string host)
        {
            IPAddress ipAddress=null;
            try
            {
                if (!IPAddress.TryParse(host, out ipAddress))
                {
                    ///Commented out by: Jamie Casterline 11/02/2010
                    ///This code will not work with Windows Vista/7 because of IPV6 address
                    //ipAddress = Dns.GetHostEntry(host).AddressList[0];

                    ///This code will look through all IPAddresses returned and put the first value that is InterNetwork into ipAddress.
                    ///This will only work as expected if the DNS is mapped to ONE ip address.
                    ///If there are multiple ip addresses, the lowest numerical ip address will be returned.
                    IPAddress[] addresses = Dns.GetHostAddresses(host);
                    foreach (IPAddress addr in Dns.GetHostEntry(host).AddressList)
                    {
                        if (addr.AddressFamily == AddressFamily.InterNetwork)
                        {
                            ipAddress = addr;
                            break;
                        }
                    }
                }
            }
            catch (SocketException se)
            {
                //ummm... do nothing
            }

            return ipAddress;
        }
    }
    #endregion
}
